package com.ys.service.purchase.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.dto.AddDto;
import com.ys.entity.base.CheckByGrid;
import com.ys.entity.flow.YspModel;
import com.ys.entity.purchase.TcgInvoiceOffset;
import com.ys.entity.purchase.TcgInvoiceOffsetItem;
import com.ys.entity.purchase.TcgPurchaseContractItem;
import com.ys.entity.sys.*;
import com.ys.enume.flow.FlowEnum;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.mapper.product.ProductMapper;
import com.ys.mapper.purchase.TcgInvoiceOffsetItemMapper;
import com.ys.mapper.purchase.TcgInvoiceOffsetMapper;
import com.ys.mapper.purchase.TcgPurchaseContractItemMapper;
import com.ys.service.flow.YspTaskService;
import com.ys.service.purchase.TcgInvoiceOffsetService;
import com.ys.util.CheckUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 发票预核销单、管理
 */
@Service("tcgInvoiceOffsetService")
public class TcgInvoiceOffsetServiceImpl implements TcgInvoiceOffsetService {
	private static final Logger logger = LoggerFactory.getLogger(TcgInvoiceOffsetServiceImpl.class);

	@Autowired
	private TcgInvoiceOffsetMapper tcgInvoiceOffsetMapper;

	@Autowired
	private TcgInvoiceOffsetItemMapper tcgInvoiceOffsetItemMapper;

	@Autowired
	private YspTaskService yspTaskService;

	@Autowired
	private CheckUtil checkUtil;

	@Autowired
	private ProductMapper productMapper;

	@Autowired
	private TcgPurchaseContractItemMapper tcgPurchaseContractItemMapper;

	private final Long GRID = 52L;

	/**
	 * 新增
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R add(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("新增传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TcgInvoiceOffset entity = JSON.parseObject(JSON.toJSONString(params), TcgInvoiceOffset.class);
		entity.setStatus(1);//状态
		entity.setEffectStock(0);//审批状态
		entity.setInvoiceState(0);//发票状态(0否、1是、2删除/取消)
		entity.setCustomsState(0);//报关完整性(0否、1是)
		entity.setBackTaxState(0);//退税状态(0否、1是)

		//获取制单人信息
		TsUserChange tsUserChange = new TsUserChange().setUserId(ShiroUtils.getUserId()).setStatus(1).queryFirst();
		if(tsUserChange!=null){
			entity.setCreateChangeId(tsUserChange.getId());//制单人变更信息
		}else {
			return R.error("未查询到制单人信息！");
		}

		//保存列表信息
		R saveItemRes = saveItem(params,entity);
		if(saveItemRes.getCode()==1){
			return saveItemRes;
		}

		//新增
		tcgInvoiceOffsetMapper.insert(entity);

		YsMenu ysMenu = new YsMenu().setId(menuId).queryFirst();
		if (ysMenu.getFlowModelId().longValue() != 0L) {
			YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
			String codeModel = yspModel.getCode();
			String createUserId = ShiroUtils.getUserId();
			yspTaskService.init(codeModel, entity.getBid(), createUserId);
		}
		//return R.ok(EditDto.closeAndReload());
		return R.ok(AddDto.gotoEdit("/web/purchase/tcgInvoiceOffset/toEdit?bid=" + entity.getBid()));
	}


	/**
	 * 修改
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R update(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("修改传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TcgInvoiceOffset entity = JSON.parseObject(JSON.toJSONString(params), TcgInvoiceOffset.class);
		// 验证状态
		YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
		if (ysProcInst == null) {
			return R.error("审批数据不存在，无法编辑");
		} else if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.INIT.value) {
			return R.error("已流转，无法编辑");
		}

		//保存列表信息
		R saveItemRes = saveItem(params,entity);
		if(saveItemRes.getCode()==1){
			return saveItemRes;
		}
		tcgInvoiceOffsetMapper.update(entity);
		return R.ok();
	}


	//保存子列表信息
	public R saveItem(Map<String, Object> params, TcgInvoiceOffset entity) throws Exception{
		//保存列表信息
		List<Map<String, Object>> subDataList = new ArrayList<>();
		if(params.get("subData")!=null){
			JSONArray subData = JSON.parseArray(params.get("subData").toString());
			CheckByGrid checkByGrid = checkParamsByGrid(subData,GRID,params);
			if(checkUtil.isNotNullByObject(checkByGrid.getErrMsg())){
				return R.error(checkByGrid.getErrMsg());
			}
			subDataList = checkByGrid.getSubDataList();
		}else {
			return R.error("列表信息为空！");
		}

		//先删除详情数据
		productMapper.deleteTcgInvoiceOffsetItemByPbid(entity.getBid());
		//再新增
		for (int i = 0; i < subDataList.size(); i++) {
			Map<String, Object> item = subDataList.get(i);
			TcgInvoiceOffsetItem itemInfo = JSON.parseObject(JSON.toJSONString(item), TcgInvoiceOffsetItem.class);
			itemInfo.setStatus(1);
			itemInfo.setPbid(entity.getBid());
			itemInfo.setCustomsNum(0);
			itemInfo.setCustomsState(0);
			//新增
			tcgInvoiceOffsetItemMapper.insert(itemInfo);
		}
		return R.ok();
	}


	//删除
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R del(Long id) throws Exception{
		if (id == null) {
			return R.error("ID不能为空");
		}
		TcgInvoiceOffset entity = new TcgInvoiceOffset().setId(id).queryFirst();
		if (entity.getEffectStock() == FlowEnum.EffectStock.EFFECTED.value) {
			return R.error("已生效数据无法删除");
		}
		// 验证是否制单人
		String loginUserId = ShiroUtils.getUserId();
		TsUserChange tsUserChange = new TsUserChange().setId(entity.getCreateChangeId()).queryFirst();
		if (!tsUserChange.getUserId().equals(loginUserId) && !"admin".equals(loginUserId)) {
			return R.error("非制单人，无法删除");
		}
		//删除
		tcgInvoiceOffsetMapper.deleteTrue(id);
		//删除列表信息
		productMapper.deleteTcgInvoiceOffsetItemByPbid(entity.getBid());
		//删除流程
		yspTaskService.flowDelete(entity.getBid(), loginUserId);
		return R.ok();
	}


	/**
	 * 流转通过
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R flowPass(Long id,String userId	) throws Exception {
		//获取单据信息
		TcgInvoiceOffset entity = new TcgInvoiceOffset().setId(id).queryFirst();
		if (entity == null) {
			return R.error("该单据不存在,请核实后再操作!");
		}

		Flow f = yspTaskService.flowPass(entity.getBid(),userId);

		if (f.getCode() == Flow.Code.FAILED.value) {
			return R.error(f.getMsg());
		} else {
			if (f.getState() == Flow.State.FINISH.value) {
				return flowFinish(entity);
			}
			return R.ok();
		}
	}

	/**
	 * 流转结束
	 */
	public R flowFinish(TcgInvoiceOffset entity) throws Exception {

		YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
		if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.FINISH.value) {
			return R.error("状态有误");
		}
		Date theDate = new Date();
		entity.setEffectStock(FlowEnum.EffectStock.EFFECTED.value);
		entity.setUpdateTime(theDate);

		//获取子表信息
		List<TcgInvoiceOffsetItem> itemList = new TcgInvoiceOffsetItem().setPbid(entity.getBid()).queryList();
		if(itemList==null || itemList.size()<=0){
			return R.error("未查询到对应的子表信息");
		}

		//拼接采购合同id
		String contractIds = "";
		for( TcgInvoiceOffsetItem item:itemList ){
			if(contractIds.equals("")){
				contractIds = item.getPurchaseContractItemId().toString();
			}else {
				contractIds = contractIds + ","+ item.getPurchaseContractItemId().toString();
			}
		}

		//获取采购合同信息
		List<TcgPurchaseContractItem> tcgPurchaseContractItemList = new TcgPurchaseContractItem()
				.where("A.Id IN (" + contractIds + ")")
				.queryList();
		if(tcgPurchaseContractItemList==null || tcgPurchaseContractItemList.size()<=0){
			return R.error("未查询到采购合同信息");
		}

		//变更采购合同管理数据字段
		//遍历详情信息
		for (int i=0;i<itemList.size();i++){
			TcgInvoiceOffsetItem item = itemList.get(i);
			//获取对应的采购合同信息
			List<TcgPurchaseContractItem> contractItemListById = tcgPurchaseContractItemList.stream()
					.filter(contractItem->contractItem.getId().equals(item.getPurchaseContractItemId()))
					.collect(Collectors.toList());
			if(contractItemListById.size()<=0){
				throw new IllegalArgumentException("第"+(i+1)+"行列表信息：未查询到对应的采购合同管理信息");
			}
			TcgPurchaseContractItem tcgPurchaseContractItem = contractItemListById.get(0);

			//1、采购核销完整性 产生完整性的判断
			if(tcgPurchaseContractItem.getSubWriteOffState() == 1){//采购核销完整性（0否、1是）
				throw new IllegalArgumentException("第"+(i+1)+"行列表信息：对应的采购核销完整性已完整，无法再进行核销");
			}

			//2、子件核销数量 = 子件已核销数量+发票本次核销数量
			int subWriteOffNum = tcgPurchaseContractItem.getSubWriteOffNum() + item.getOffsetNum();
			//判断核销数量是否大于子件采购数量
			int countNum = subWriteOffNum - tcgPurchaseContractItem.getSubPurchaseNum();
			if(countNum >0 ){//大于子件采购数量
				throw new IllegalArgumentException("第"+(i+1)+"行列表信息：子件核销数量超过了采购合同中的采购数量");
			}
			if(subWriteOffNum - tcgPurchaseContractItem.getSubPurchaseNum() == 0){//等于
				tcgPurchaseContractItem.setSubWriteOffState(1);//采购核销完整性（0否、1是）
			}
			tcgPurchaseContractItem.setSubWriteOffNum(subWriteOffNum);

			//修改采购合同单信息
			tcgPurchaseContractItemMapper.update(tcgPurchaseContractItem);
		}

		//修改信息
		tcgInvoiceOffsetMapper.update(entity);
		return R.ok();

	}


	//登记取消
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R cancelInfo(Long id) throws Exception{
		TcgInvoiceOffset entity = new TcgInvoiceOffset().setId(id).queryFirst();
		if(entity==null || entity.getStatus()==null){
			return R.error("未查询到发票管理表信息");
		}
		List<TcgInvoiceOffsetItem> itemList = new TcgInvoiceOffsetItem().setPbid(entity.getBid()).queryList();
		if(itemList==null || itemList.size()<=0){
			return R.error("未查询到发票管理表对应的子表信息");
		}
		//拼接采购合同id
		String contractIds = "";
		for( TcgInvoiceOffsetItem item:itemList ){
			if(contractIds.equals("")){
				contractIds = item.getPurchaseContractItemId().toString();
			}else {
				contractIds = contractIds + ","+ item.getPurchaseContractItemId().toString();
			}
		}
		//获取采购合同信息
		List<TcgPurchaseContractItem> tcgPurchaseContractItemList = new TcgPurchaseContractItem()
				.where("A.Id IN (" + contractIds + ")")
				.queryList();
		if(tcgPurchaseContractItemList==null || tcgPurchaseContractItemList.size()<=0){
			return R.error("未查询到采购合同信息");
		}

		for (int i=0;i<itemList.size();i++) {
			TcgInvoiceOffsetItem item = itemList.get(i);
			//获取对应的采购合同信息
			List<TcgPurchaseContractItem> contractItemListById = tcgPurchaseContractItemList.stream()
					.filter(contractItem -> contractItem.getId().equals(item.getPurchaseContractItemId()))
					.collect(Collectors.toList());
			if(contractItemListById.size()<=0){
				throw new IllegalArgumentException("未查询到对应的采购合同管理信息");
			}
			TcgPurchaseContractItem tcgPurchaseContractItem = contractItemListById.get(0);
			if(item.getCustomsNum()>0){
				throw new IllegalArgumentException("报关数量＞0 ，不可发票登记取消");
			}

			//减少对应采购合同管理对应子件的子件核销数量
			int subWriteOffNum = tcgPurchaseContractItem.getSubWriteOffNum();//子件核销数量
			int offsetNum = item.getOffsetNum();//发票本次核销数量
			int countNum = subWriteOffNum - offsetNum;
			tcgPurchaseContractItem.setSubWriteOffNum(countNum);//设置：子件核销数量
			tcgPurchaseContractItem.setSubWriteOffState(0);//采购核销完整性（0否、1是）

			//修改采购合同单信息
			tcgPurchaseContractItemMapper.update(tcgPurchaseContractItem);

			item.setStatus(0);//将子表信息状态修改
			tcgInvoiceOffsetItemMapper.update(item);
		}
		entity.setInvoiceState(2);
		//修改信息
		tcgInvoiceOffsetMapper.update(entity);
		return R.ok();
	}

	/**
	 * 参数验证
	 */
	public String checkParams(Map<String, Object> params, Long menuId) throws Exception {
		//获取pc字段数据
		List<YsCol> listField = new YsCol()
				.where("A.MenuId = "+menuId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		//验证必填字段的非空；其他字段的长度限制、类型
		String backMsg = checkUtil.checkTableColLengthAndDataType("TCG_InvoiceOffset",listField,params,ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1);

		return backMsg;
	}


	/**
	 * 子表参数验证
	 */
	public CheckByGrid checkParamsByGrid(JSONArray subDataArray, Long gridId,Map<String, Object> params) throws Exception {
		CheckByGrid checkByGrid = new CheckByGrid();
		//获取pc字段数据
		List<YsGridCol> listField = new YsGridCol()
				.setGridId(gridId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		String backMsg = "";
		List<Map<String, Object>> subDataList = new ArrayList<>();

		if(subDataArray!=null && subDataArray.size()>0){
			for (int i = 0; i < subDataArray.size(); i++) {
				JSONObject jsonObject = subDataArray.getJSONObject(i);
				Map<String, Object> paramsNewByRecord = new HashMap<>();
				for (String key : jsonObject.keySet()) {
					paramsNewByRecord.put(key, jsonObject.get(key));
				}
				subDataList.add(paramsNewByRecord);
			}
			//验证
			for(int i = 0;i<subDataList.size();i++){
				String backMsgByRow = "";
				Map<String, Object> subData = subDataList.get(i);
				//验证必填字段的非空；其他字段的长度限制、类型
				backMsgByRow += checkUtil.checkTableColLengthAndDataTypeByGrid(
						"TCG_InvoiceOffsetItem",
						listField,
						subData,
						ysColItem->
								ysColItem.getCode().equals("purchaseContractBid")
								|| ysColItem.getCode().equals("offsetNum")
										|| ysColItem.getCode().equals("offsetAmount")
										|| ysColItem.getCode().equals("invoiceModelNo")
										|| ysColItem.getCode().equals("invoiceName")

				);
				if(checkUtil.isNotNullByObject(subData.get("offsetNum"))){
					if(Integer.parseInt(subData.get("offsetNum").toString())<=0){
						backMsgByRow += "发票本次核销数量应大于0；";
					}
					if(!checkUtil.isInt(subData.get("offsetNum").toString())){
						backMsgByRow += "发票本次核销数量应是整数；";
					}
				}
				if(checkUtil.isNotNullByObject(subData.get("vnameByItem")) && checkUtil.isNotNullByObject(params.get("vname"))){
					if(!subData.get("vnameByItem").toString().equals(params.get("vname").toString())){
						backMsgByRow += "购买方公司名称应与母表一致；";
					}
				}
				if(checkUtil.isNotNullByObject(subData.get("partnerNameByItem")) && checkUtil.isNotNullByObject(params.get("partnerName"))){
					if(!subData.get("partnerNameByItem").toString().equals(params.get("partnerName").toString())){
						backMsgByRow += "供应方公司名称应与母表一致；";
					}
				}

				if(checkUtil.isNotNullByObject(backMsgByRow)){
					backMsg += "列表第" + (i+1) + "行，" + backMsgByRow;
				}
			}
		}else{
			backMsg = "列表信息为空";
		}
		checkByGrid.setErrMsg(backMsg);
		checkByGrid.setSubDataList(subDataList);

		return checkByGrid;
	}


	//获取列表数据
	@Override
	@Transactional
	public Map<String,Object> getExtraParam( String bid) throws Exception{
		Map<String,Object> extraParam = new TcgInvoiceOffset()

				.addLeftJoin("YS_ProcInst P ON P.Bid = A.Bid ")
				.addField("FORMAT(P.UpdateTime, 'yyyy-MM-dd HH:mm:ss') AS auditingTime")//审核时间

				.addLeftJoin("TB_CompanyInfo C ON C.Vid = A.CompanyVid ")//公司信息表
				.addField("C.Vname AS vname")//购买方公司名称
				.addField("C.Tax AS tax")//购买方公司税号

				.addLeftJoin("TCW_PartnerBankInfo PBI ON PBI.Id = A.PartnerBankInfoId ")//合作商银行账户管理
				.addField("PBI.PartnerName AS partnerName")//供应方公司名称
				.addField("PBI.Vgssh AS vgssh")//供应方公司税号

				.setBid(bid)
				.queryFirstMap();
		return extraParam;
	}
	//获取子列表数据
	@Override
	@Transactional
	public List<Map<String, Object>> getItemList( String bid) throws Exception{
		List<Map<String, Object>> itemList = new TcgInvoiceOffsetItem()
				.addLeftJoin("TCG_PurchaseContractItem PCI ON PCI.Id = A.PurchaseContractItemId ")//采购合同管理子表
				.addField("PCI.Pbid AS purchaseContractBid")//采购合同单号
				.addField("PCI.SubBomNumber AS subBomNumber")//子件BOM数量
				.addField("PCI.SubPurchaseNum AS subPurchaseNum")//子件采购数量
				.addField("PCI.SubPurchasePrice AS subPurchasePrice")//子件采购单价
				.addField("PCI.SubWriteOffNum AS subWriteOffNum")//子件已核销数量

				.addLeftJoin("TCG_PurchaseContract PC ON PC.Bid = PCI.Pbid ")//采购合同管理
				//.addLeftJoin("TCG_PurchaseAppointOrder O ON O.Id = PC.PurchaseAppointOrderId ")//预约采购管理表
				.addLeftJoin("TB_CompanyInfo CI ON CI.Vid = PC.CompanyInfoVid ")//公司信息
				.addField("CI.Vname AS vnameByItem")//购买方公司名称
				.addLeftJoin("TCW_PartnerBankInfo PB ON PB.Id = PC.PartnerBankInfoId ")//合作商银行账户管理表
				.addField("PB.PartnerName AS partnerNameByItem")//供应方公司名称 、合作方名称

				.addLeftJoin("TCG_PurchaseAppointOrderProductComponent PAC ON PAC.Id = PCI.OrderProductComponentId")//预约采购管理子件表
				.addLeftJoin("TCG_PurchaseAppointOrderItem PAOI ON PAOI.Id = PAC.Pid")//预约采购管理母件表
				.addLeftJoin("TCG_PurchaseAppointOrder PPC ON PPC.Bid = PAOI.Pbid")//预约采购单母表
				.addLeftJoin("THR_OperateCompanyApply OCA ON OCA.Vgsbm = PPC.Vgsbm")//运营公司管理表

				.addField("PPC.Bid AS appointOrderBid")//预约采购单单号
				.addField("PPC.Vgsbm AS vgsbm")//运营公司编码
				.addField("OCA.Vgsjc AS vgsjc")//运营公司简称
				.addField("PAOI.ProductCode AS productCode")//商品编码
				.addField("PAOI.ProductName AS productName")//商品名称
				.addField("PAOI.CodeMerge AS codeMerge")//合并商品编码
				.addField("PAC.SubCode AS subCode")//子件编码
				.addField("PAC.SubName AS subName")//子件名称
				.addField("PAC.SubCodeMerge AS subCodeMerge")//子件合并编码

				.setPbid(bid)
				.queryMap();
		return itemList;
	}


}
